//你好
const { def, base, intField, setEvent, regFieldGetSet, regEvent } = require("./jsdemo_windows.common.cpp.js");

const label = String.raw/* cpp */`
  class Label : public Window{
    public:
    Label();
    ~Label();

    void render(int mask);
    void mouseDown(int x, int y, int e);
    void mouseUp(int x, int y, int e);
    void mouseMove(int x, int y, int e);
    void keyEvent(int key, int chr);

    char* title;
    int textX;
    int textY;
    
  };

  Label::Label() : Window() {
    title = 0;
    width = 100;
    height = 26;
    textX = 5;
    textY = 5;
  }
  Label::~Label(){
    printf("~Label\n");
    if(title){
      free(title);
    }
  }

  void Label::render(int mask){
    if((needRefresh)){
      if((beforeRender.tag & mask)!=JS_TAG_UNDEFINED){
        jsCall(beforeRender);
      }
        
      Window::render(0);
      int shade = getRGB565(0x606060);
      int bg = getRGB565(bg_color);

      int top = 0;
      if(windows){
        top = this == windows->topWindow;
      }

      paint_pattern(abs_pos_x            , abs_pos_y             ,     2, height, (shade<<16) | shade, 0);
      paint_pattern(abs_pos_x            , abs_pos_y             , width,      2, (shade<<16) | shade, 0);
      paint_pattern(abs_pos_x + width - 2, abs_pos_y             ,     2, height, (shade<<16) | shade, 0);
      paint_pattern(abs_pos_x            , abs_pos_y + height - 2, width,      2, (shade<<16) | shade, 0);
      paint_pattern(abs_pos_x + 2        , abs_pos_y + 2         , width-4, height-4, bg, 0);

      if(title){
        FILE* s = getStream(textX, textY, width, height);
        fprintf(s, title);
      }

      if((afterRender.tag & mask)!=JS_TAG_UNDEFINED){
        jsCall(afterRender);
      }
      if(mask){
        needRefresh = 0;
      }
    }

  }

  void Label::mouseDown(int x, int y, int e){
  }
  void Label::mouseUp(int x, int y, int e){
  }
  void Label::mouseMove(int x, int y, int e){
  }
  void Label::keyEvent(int key, int chr){
  }

  static void js_label_calc_size(Label *p){
    p->height = 26;
    p->width = strlen(p->title)*8 + 10;
  }
  static JSValue js_label_ctor(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv) {
    Label* p = new Label();
    JSValue obj = JS_NewObjectClass(ctx, js_label_class_id);
    p->js_obj = obj;
    JS_SetOpaque(obj, p);
    return obj;
  }
  static void js_label_finalizer(JSRuntime *rt, JSValue val) {
    Label *p = (Label*)JS_GetOpaque(val);
    if(p){
      delete p;
    }
  }

  static JSValue js_label_set_title(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) {
    Label *p = (Label*)JS_GetOpaque(this_val);
    if(p){
      if(p->title){
        free(p->title);
      }
      size_t len; char* str = (char*)JS_ToCStringLen(ctx, &len, argv[0]);
      p->title = (char*)malloc(len+1);
      memcpy(p->title, str, len+1);
      JS_FreeCString(ctx, str);
      js_label_calc_size(p);
      p->needRefresh = 1;
    }
    return JS_UNDEFINED;
  }

  void label_init(JSValue* window_ctor, JSValue* window_proto) {
    JS_NewClassID(&js_label_class_id);
    JSClassDef label_def = {
      .class_name = "Label",
      .finalizer = js_label_finalizer,
    };
    JS_NewClass(rt, js_label_class_id, &label_def);

    JSValue label_proto = JS_NewObject(ctx);

    JS_DefinePropertyGetSet(ctx, label_proto, JS_NewAtom(ctx, "title"), JS_UNDEFINED, JS_NewCFunction(ctx, js_label_set_title, "title", 1), JS_PROP_CONFIGURABLE | JS_PROP_ENUMERABLE);

    JS_SetClassProto(ctx, js_label_class_id, label_proto);

    JSValue label_ctor = JS_NewCFunction2(ctx, js_label_ctor, "Label", 2, JS_CFUNC_constructor, 0);
    JS_SetConstructor(ctx, label_ctor, label_proto);
    JS_SetPropertyStr(ctx, global, "Label", label_ctor);

    JS_SetPrototype(ctx, label_proto, *window_proto);
    JS_SetPrototype(ctx, label_ctor, *window_ctor);
  }  
`;

module.exports = { label };


